package buco.core.api;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class ImportCompositionCommand extends Command<File, Void>  {
	@Override
	public Void execute() throws Exception {
		File file = this.parameters; 
		FileInputStream fis = new FileInputStream(file);
        ZipInputStream zis = new  ZipInputStream(new BufferedInputStream(fis));
        ZipEntry entry; 
        String compositionJson = null; 
        HashMap<String, Integer> fileMapping = new HashMap<String, Integer>(); 
        
        while((entry = zis.getNextEntry()) != null) {
        	String name = entry.getName(); 
        	ByteArrayOutputStream out = new ByteArrayOutputStream();
        	byte[] buffer = new byte[1024];
        	int count; 
        	while ( (count = zis.read(buffer)) != -1 ){
                out.write(buffer, 0, count);
        	}        	
        	
        	buffer = out.toByteArray(); 
        	
        	if(name.toLowerCase().endsWith(".jar")) {
        		int fileID = fileManager.addFile(name, buffer); 
        		fileMapping.put(name, fileID); 
        	} else if(name.toLowerCase().endsWith(".json")) { 
        		compositionJson = new String(buffer, "UTF8"); 
        	}
        }
        
        if(compositionJson != null) {
        	JSONParser parser = new JSONParser(); 
        	JSONObject objComposition = (JSONObject) parser.parse(compositionJson);
        	createComposition(objComposition, fileMapping); 
        }
		return null;
	}
	
	private void createComposition(JSONObject obj, HashMap<String, Integer> fileMapping) { 
		JSONArray bundlesArr = (JSONArray) obj.get("bundles"); 
		JSONArray wiresArr = (JSONArray) obj.get("wires");
		
		for(int i=0; i < bundlesArr.size(); i++) {
			JSONObject bundleObj = (JSONObject) bundlesArr.get(i); 			
			int left = readInt32(bundleObj, "left"); 
			int top = readInt32(bundleObj, "top");
			String file = bundleObj.get("file").toString(); 
			int fileID = fileMapping.get(file); 
			
			Bundle bundle = Bundle.fromJarFile(fileManager.getFileByID(fileID));
			bundle.setFileID(fileID);			
			bundle.setCustomProperty("top", top);
			bundle.setCustomProperty("left", left); 
			
			try {
				composition.addBundle(bundle);
			} catch (DuplicateBundleException e) {
				e.printStackTrace();
			} 			
		}
	
		for(int i=0; i < wiresArr.size(); i++) {
			JSONObject wireObj = (JSONObject) wiresArr.get(i);
			int from = readInt32(wireObj, "from");
			int to = readInt32(wireObj, "to");
			boolean active = readBoolean(wireObj, "active");  
						
			BundleWire wire = composition.getWire(composition.getBundleByID(from), composition.getBundleByID(to));
			if(wire != null) {
				wire.setIsActive(active);
			}			
		}
	}

	@Override
	public boolean canUndo() { 
		return false;
	}
	
	@SuppressWarnings("rawtypes")
	private int readInt32(Map map, String parameter) {
		return ((java.lang.Number)map.get(parameter)).intValue();
	}
	
	private boolean readBoolean(Map map, String parameter) {
		return (boolean) map.get(parameter); 
	}
	
}


